package com.ny.zmb.openapi.gMdemo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ny.zmb.openapi.config.YsConfig;
import com.ny.zmb.openapi.util.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 商户入网申请
 */
public class YsfApiDemo {

    private final String ALLCHAR = "0123456789ABCDEF";

    /**
     * 发起方商户号 服务商在银盛给自己开设的商户号，即可当作发起方商户号
     * 生产环境需要使用自己的发起发商户号，并找相应的对接人员开通所需要的接口权限，并告知是国密还是RSA
     */
    private final String CERT_ID = "826513173750017";

    /**
     * 银盛端公钥证书
     * 生产环境需要自行去开放平台上下载银盛公钥证书，也可以找对接人提供
     */


    private String YS_PUBLIC_CER_PATH = new YsConfig().getYsPublicCerPath();

    /**
     * 商户端私钥证书
     * 生产环境需要使用自己生产的私钥证书
     */
    private String MERC_PRIVATE_FILE = new YsConfig().getMercPrivateFile();

    /**
     * 商户端私钥证书密码
     * 生产环境需要使用自己私钥的密码
     */
    private final String MERC_PRIVATE_FILE_PASSWORD = "197Aa2569";

    /**
     * 请求地址域名
     */
    private final String HTTP_NET = "https://ysgate.ysepay.com";
    //测试 https://appdev.ysepay.com
    //生产 https://ysgate.ysepay.com


    public void main(String[] args) throws Exception {
        /** 1、资料上送*/
        //addCustInfoApplyDemo();

        /** 2、图片上送*/
        //imgUploadDemo();

        /** 3、资料修改*/
        //modifyCustInfoDemo();

        /** 4、资料确认*/
        //auditCustInfoApplyDemo();

        /** 5、商户状态查询*/
        //queryCustApplyDemo();

        /** 6、合同签约申请*/
        //smscSignDemo();

        /** 7、重发签约短信或者邮件*/
        //sendSmsOrEmailMsgDemo();

        /** 8、签约状态查询*/
        //queryContractDemo();

        /** 9、电子合同下载*/
        //downloadContractDemo();

        /** 10、基本信息变更申请*/
        //changeMercBaseInfoDemo();

        /** 11、变更图片上传*/
        //uploadChangePicDemo();

        /** 12、基本信息变更审核 */
        //changeBaseAuditDemo();

        /** 13、结算信息变更申请 */
        //changeMercStlAccInfoDemo();

        /** 14、结算信息变更审核*/
        //changeStlAuditDemo();

        /** 15、费率信息变更申请*/
        //changeRateDemo();

        /** 16、费率信息变更审核*/
        //changeRateAuditDemo();

        /** 17、变更状态查询*/
        //queryCustChangeDemo();

        /** 18、报备*/
        //sweepreportDemo();

        /** 19 重新报备*/
        //reportAgainDemo();

        /** 20 开通/关闭线上D0权限*/
        //authorityOnline()
    }


    /**
     * 商户入网
     */
    public void addCustInfoApplyDemo() throws Exception {
        //请求接口
        String HTTP_URL = HTTP_NET + "/openapi/t1/smsc/addCustInfoApply";
        //测试 https://appdev.ysepay.com/openapi/t1/smsc/addCustInfoApply
        //生产 https://ysgate.ysepay.com/openapi/t1/smsc/addCustInfoApply

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.addCustInfoApply");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //基本信息
        bizContentMap.put("custInfo", getCustInfo());
        //法人信息
        bizContentMap.put("crpInfo", getCrpInfo());
        //结算信息
        bizContentMap.put("stlAccInfo", getStlAccInfo());
        //营业信息
        bizContentMap.put("busInfo", getBusInfo());
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    return;
                }
            } else {
                System.out.println("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
                return;
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            System.out.println("商户入网申请失败:" + e.getMessage());
        }
    }

    /**
     * 上传变更图片
     */
    public void uploadChangePicDemo() throws Exception {
        String HTTP_URL = HTTP_NET + "/openapi/file/smsc/uploadChangePic";
        //测试 https://appdev.ysepay.com/openapi/file/smsc/uploadChangePic
        //生产 https://ysgate.ysepay.com/openapi/file/smsc/uploadChangePic

        File file = new File("C:\\Users\\MI\\Desktop\\testPic\\test2.png");

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "file.smsc.uploadChangePic");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        reqMap.put("check", check);//加密后的密钥

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //meta媒体文件元素信息
        Map<String, String> metaJSONObject = new HashMap<>();
        FileInputStream fileInputStream = new FileInputStream(file);
        String sha256 = DigestUtils.sha256Hex(fileInputStream);
        metaJSONObject.put("sha256", sha256);
        //图片类型， A001-营业执照 A002-法人身份证正面(头像面) A003-法人身份证反面(国徽面) A004-结算账户正面(卡号面) A005-结算账户反面 A006-商户门头照片 A007-内景照片 A008-收银台照片 A009-手持身份证合影照片 A010-收单协议盖章页 A011-开户许可证 A012-收单协议首页 A013-非法人身份证头像面 A014-非法人身份证国徽面 B001-租赁合同 第一页 B002-租赁合同 第二页 B003-租赁合同 第三页 B004-法人/非法人手持授权书 B005-法人/非法人结算授权书 B006-租赁面积图片 B007-经营业务图片 B008-其他1 B009-其他2
        metaJSONObject.put("picType", "B008");
        //变更申请流水号 变更申请成功后返回
        metaJSONObject.put("changeFlowId", "CHG202204200000139");
        //图片名称
        metaJSONObject.put("picNm", "XJG");
        //设置媒体元素信息
        bizContentMap.put("meta", metaJSONObject);

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizContentMap, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.sendPostFile(HTTP_URL, reqMap, file);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    return;
                }
            } else {
                System.out.println("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
                return;
            }

            /** 9、针对自己的业务，根据返回的结果的code、subCode、businessData 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            System.out.println("图片上传demo失败:" + e);
        }
    }

    /**
     * 图片上传demo
     */
    public void imgUploadDemo() throws Exception {
        String HTTP_URL = HTTP_NET + "/openapi/file/smsc/upload";
        //测试 https://appdev.ysepay.com/openapi/file/smsc/upload
        //生产 https://ysgate.ysepay.com/openapi/file/smsc/upload

        File file = new File("C:\\Users\\MI\\Desktop\\testPic\\test2.png");

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "file.smsc.upload");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        reqMap.put("check", check);//加密后的密钥

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //meta媒体文件元素信息
        Map<String, String> metaJSONObject = new HashMap<>();
        FileInputStream fileInputStream = new FileInputStream(file);
        String sha256 = DigestUtils.sha256Hex(fileInputStream);
        metaJSONObject.put("sha256", sha256);
        //图片类型， A001-营业执照 A002-法人身份证正面(头像面) A003-法人身份证反面(国徽面) A004-结算账户正面(卡号面) A005-结算账户反面 A006-商户门头照片 A007-内景照片 A008-收银台照片 A009-手持身份证合影照片 A010-收单协议盖章页 A011-开户许可证 A012-收单协议首页 A013-非法人身份证头像面 A014-非法人身份证国徽面 B001-租赁合同 第一页 B002-租赁合同 第二页 B003-租赁合同 第三页 B004-法人/非法人手持授权书 B005-法人/非法人结算授权书 B006-租赁面积图片 B007-经营业务图片 B008-其他1 B009-其他2
        metaJSONObject.put("picType", "A010");
        //图片名称
        metaJSONObject.put("picNm", "XJG");
        //流水号
        metaJSONObject.put("sysFlowId", "APPL202204201425170000448");
        //设置媒体元素信息
        bizContentMap.put("meta", metaJSONObject);

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizContentMap, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            //云商服图片上传接口调用的发送文件接口和支付宝实名认证的文件上传接口调用的方法不一样，请注意！！！
            String result = HttpRequestUtil.sendPostFile(HTTP_URL, reqMap, file);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code、subCode、businessData 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            System.out.println("图片上传demo失败:" + e);
        }
    }

    /**
     * 商户入网申请修改
     *
     * @throws Exception
     */
    public void modifyCustInfoDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/modifyCustInfoApply";
        //测试 https://appdev.ysepay.com/openapi/smsc/modifyCustInfoApply
        //生产 https://ysgate.ysepay.com/openapi/smsc/modifyCustInfoApply

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.modifyCustInfoApply");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //入网申请流水
        bizContentMap.put("sysFlowId", "APPL202206151104150002420");
        //基本信息
        bizContentMap.put("custInfo", getModeifyCustInfo());
        //法人信息
        bizContentMap.put("crpInfo", getModeifytCrpInfo());
        //结算信息
        bizContentMap.put("stlAccInfo", getModeifyStlAccInfo());
        //营业信息
        bizContentMap.put("busInfo", getModeifyBusInfo());
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 商户入网审核
     *
     * @throws Exception
     */
    public void auditCustInfoApplyDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/t1/smsc/auditCustInfoApply";
        //测试 https://appdev.ysepay.com/openapi/t1/smsc/auditCustInfoApply
        //生产 https://ysgate.ysepay.com/openapi/t1/smsc/auditCustInfoApply

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.auditCustInfoApply");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //入网申请流水
        bizContentMap.put("sysFlowId", "APPL202204201425170000448");
        //审核标志 Y通过,N拒绝
        bizContentMap.put("auditFlag", "Y");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 查询商户状态
     *
     * @throws Exception
     */
    public void queryCustApplyDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/queryCustApply";
        //测试 https://appdev.ysepay.com/openapi/smsc/queryCustApply
        //生产 https://ysgate.ysepay.com/openapi/smsc/queryCustApply

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.queryCustApply");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //入网申请流水
        bizContentMap.put("sysFlowId", "APPL202204201425170000448");

        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 合同签约
     *
     * @throws Exception
     */
    public void smscSignDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/t1/smsc/sign";
        //测试 https://appdev.ysepay.com/openapi/t1/smsc/sign
        //生产 https://ysgate.ysepay.com/openapi/t1/smsc/sign

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.sign");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //客户号
        bizContentMap.put("custId", "2022042005771626");
        //到账方式 00-扫码工作日到账01-扫码实时到账10-刷卡工作日到账11-刷卡实时到账20-D1到账 允许多选用“|”分隔 T1工作日到账必选
        bizContentMap.put("busOpenType", "00|01|10|11|20");
        //合同类型 1-纸质合同 2-电子合同
        bizContentMap.put("contractType", "2");
        //签约通知标识 contractType=2时必填 0(短信+邮件) 1(短信) 2(邮件) 3(不通知)
        bizContentMap.put("isSendConMsg", "0");
        //异步通知url
        bizContentMap.put("notifyUrl", "http://www.baidu.com");
        //扫码工作日到账费率 busOpenType=00时必填
        bizContentMap.put("codeScanT1Fee", getCodeScanT1Fee());
        //扫码实时到账垫资费 busOpenType=01时必填
        bizContentMap.put("codeScanD0Fee", getCodeScanD0Fee());
        //刷卡工作日到账费率 busOpenType=10时必填
        bizContentMap.put("swCardT1Fee", getSwCardT1Fee());
        //刷卡实时到账垫资费 busOpenType=11时必填
        bizContentMap.put("swCardD0Fee", getSwCardD0Fee());
        //天天到账垫资费 busOpenType=20时必填
        bizContentMap.put("d1Fee", getD1Fee());
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 重发签约短信或邮件
     *
     * @throws Exception
     */
    public void sendSmsOrEmailMsgDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/sign/sendSmsOrEmailMsg";
        //测试 https://appdev.ysepay.com/openapi/smsc/sign/sendSmsOrEmailMsg
        //生产 https://ysgate.ysepay.com/openapi/smsc/sign/sendSmsOrEmailMsg

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.sign.sendSmsOrEmailMsg");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //签约ID,发起签约时候返回
        bizContentMap.put("signId", "MAN202204200000567");
        //签约通知标识 contractType=2时必填 0(短信+邮件) 1(短信) 2(邮件) 3(不通知)
        bizContentMap.put("isSendConMsg", "0");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 重发签约短信或邮件
     *
     * @throws Exception
     */
    public void queryContractDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/sign/queryContract";
        //测试 https://appdev.ysepay.com/openapi/smsc/sign/queryContract
        //生产 https://ysgate.ysepay.com/openapi/smsc/sign/queryContract

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.sign.queryContract");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //权限流水号
        bizContentMap.put("authId", "AUTH202204200000567");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 电子合同下载
     *
     * @throws Exception
     */
    public void downloadContractDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/sign/downloadContract";
        //测试 https://appdev.ysepay.com/openapi/smsc/sign/downloadContract
        //生产 https://ysgate.ysepay.com/openapi/smsc/sign/downloadContract

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.sign.downloadContract");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //签约流水号,发起签约成功后返回
        bizContentMap.put("signId", "MAN202204110000441");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));

                /** 11、获取文件二进制的base64编码，生成PDF文件*/
                JSONObject jsonObject = JSONObject.parseObject(new String(data, "UTF-8"));
                String contractFileString = jsonObject.getString("contractFileString");
                byte[] fileData = Base64.decodeBase64(contractFileString);
                File file = new File("D:\\datas\\test.pdf");
                OutputStream out = new FileOutputStream(file);
                InputStream is = new ByteArrayInputStream(fileData);
                byte[] buff = new byte[1024];
                int len = 0;
                while ((len = is.read(buff)) != -1) {
                    out.write(buff, 0, len);
                }
                is.close();
                out.close();
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 商户基本信息变更申请
     *
     * @throws Exception
     */
    public void changeMercBaseInfoDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/changeMercBaseInfo";
        //测试 https://appdev.ysepay.com/openapi/smsc/changeMercBaseInfo
        //生产 https://ysgate.ysepay.com/openapi/smsc/changeMercBaseInfo

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.changeMercBaseInfo");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        /*byte[] byte1= RSA256Util.encrypt(YS_PUBLIC_CER_PATH, ByteUtil.hexStringToBytes(key));
        String check = Base64.encodeBase64String(byte1);*/
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //客户基本信息
        Map<String, Object> custInfoMap = new HashMap<>();
        custInfoMap.put("mercNm", "测试修改");//商户名称
        custInfoMap.put("mercShortNm", "测试修改");//商户简称
        custInfoMap.put("contactMail", "10xxxxxxxx@qq.com");//联系人邮箱
        custInfoMap.put("contactMan", "张三");//联系人
        custInfoMap.put("contactPhone", "157xxxxx153");//联系人电话
        custInfoMap.put("cusMgrNm", "张三");//客户经理
        custInfoMap.put("notifyUrl", "https://www.baidu.com");//异步通知地址
        //营业信息
        Map<String, Object> busInfoMap = new HashMap<>();
        busInfoMap.put("busNm", "机构测试商户1");//营业执照名称（需同时上传营业执照）
        custInfoMap.put("busCertExpire", "29991221");//营业执照有效期（要求上传营业执照图片）
        custInfoMap.put("regAddr", "故宫路1号");//注册地址（要求上传营业执照图片）
        custInfoMap.put("busAddr", "故宫路1号");//营业地址
        //法人信息
        Map<String, Object> crpInfoMap = new HashMap<>();
        busInfoMap.put("crpNm", "张三");//法人姓名（要求上传法人身份证正反面）
        busInfoMap.put("certExpire", "29991221");//证件有效期（要求上传法人身份证正反面）
        busInfoMap.put("crpPhone", "157xxxxx153");//法人手机号号码

        //客户基本信息
        bizContentMap.put("custInfo", custInfoMap);
        //营业信息
        bizContentMap.put("busInfo", busInfoMap);
        //法人信息
        bizContentMap.put("crpInfo", crpInfoMap);
        //客户号id,入网成功后返回
        bizContentMap.put("custId", "2022042005771626");

        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        //String sign= RSA256Util.sign(sb1.toString(),MERC_PRIVATE_FILE,MERC_PRIVATE_FILE_PASSWORD);
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 基本信息变更审核
     *
     * @throws Exception
     */
    public void changeBaseAuditDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/changeBaseAudit";
        //测试 https://appdev.ysepay.com/openapi/smsc/changeBaseAudit
        //生产 https://ysgate.ysepay.com/openapi/smsc/changeBaseAudit

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.changeBaseAudit");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();

        //变更申请流水号
        bizContentMap.put("changeSysFlowId", "CHG202204200000139");
        //审核标志Y审核通过，N审核拒绝
        bizContentMap.put("auditFlag", "Y");
        //审核备注
        bizContentMap.put("auditNote", "测试审核");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 结算信息变更申请
     *
     * @throws Exception
     */
    public void changeMercStlAccInfoDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/t1/smsc/changeMercStlAccInfo";
        //测试 https://appdev.ysepay.com/openapi/t1/smsc/changeMercStlAccInfo
        //生产 https://ysgate.ysepay.com/openapi/t1/smsc/changeMercStlAccInfo

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.changeBaseAudit");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        /*byte[] byte1= RSA256Util.encrypt(YS_PUBLIC_CER_PATH, ByteUtil.hexStringToBytes(key));
        String check = Base64.encodeBase64String(byte1);*/
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //结算信息
        Map<String, Object> stlAccInfoMap = new HashMap<>();
        stlAccInfoMap.put("isSettInPlatAcc", "N"); //是否结算到平台内（Y是,N否）
        stlAccInfoMap.put("isUncrpSett", "N"); //是否非法人结算（Y是,N否）
        stlAccInfoMap.put("stlAccNo", "6217902000025127559"); //结算账号
        stlAccInfoMap.put("stlAccType", "11"); //结算账户类型（11 对私 21 对公）
        stlAccInfoMap.put("stlAccNm", "张三"); //结算户名
        stlAccInfoMap.put("openCertNo", "42xxxxxxxxxxxxxx12"); //开户行证件号
        stlAccInfoMap.put("bankSubCode", "104100004013"); //支行行号
        stlAccInfoMap.put("bankMobile", "157xxxxx153"); //手机号

        //客户号id
        bizContentMap.put("custId", "2022042005771626");
        //结算信息变更
        bizContentMap.put("stlAccInfo", stlAccInfoMap);
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        //String sign= RSA256Util.sign(sb1.toString(),MERC_PRIVATE_FILE,MERC_PRIVATE_FILE_PASSWORD);
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 结算信息变更申请
     *
     * @throws Exception
     */
    public void changeStlAuditDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/changeStlAudit";
        //测试 https://appdev.ysepay.com/openapi/smsc/changeStlAudit
        //生产 https://ysgate.ysepay.com/openapi/smsc/changeStlAudit

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.changeStlAudit");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();

        //变更流水号 结算信息变更申请成功后返回
        bizContentMap.put("changeSysFlowId", "CHG202204120000125");
        //审核标志Y审核通过，N审核拒绝
        bizContentMap.put("auditFlag", "Y");
        //审核备注
        bizContentMap.put("auditNote", "测试结算信息审核");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 费率信息变更审核
     *
     * @throws Exception
     */
    public void changeRateAuditDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/changeRateAudit";
        //测试 https://appdev.ysepay.com/openapi/smsc/changeRateAudit
        //生产 https://ysgate.ysepay.com/openapi/smsc/changeRateAudit

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.changeRateAudit");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();

        //变更流水号 费率变更申请成功后返回
        bizContentMap.put("changeSysFlowId", "CHG202204120000131");
        //审核标志Y审核通过，N审核拒绝
        bizContentMap.put("auditFlag", "Y");
        //审核备注
        bizContentMap.put("auditNote", "测试结算信息审核");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 变更费率
     *
     * @throws Exception
     */
    public void changeRateDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/changeRate";
        //测试 https://appdev.ysepay.com/openapi/smsc/changeRate
        //生产 https://ysgate.ysepay.com/openapi/smsc/changeRate

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.changeRate");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        /*byte[] byte1= RSA256Util.encrypt(YS_PUBLIC_CER_PATH, ByteUtil.hexStringToBytes(key));
        String check = Base64.encodeBase64String(byte1);*/
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //客户号
        bizContentMap.put("custId", "2022042005771626");

        //扫码工作日到账费率 busOpenType=00时必填
        bizContentMap.put("codeScanT1Fee", getCodeScanT1Fee());

        //扫码实时到账垫资费 busOpenType=01时必填
        bizContentMap.put("codeScanD0Fee", getCodeScanD0Fee());

        //刷卡工作日到账费率 busOpenType=10时必填
        bizContentMap.put("swCardT1Fee", getSwCardT1Fee());

        //刷卡实时到账垫资费 busOpenType=11时必填
        bizContentMap.put("swCardD0Fee", getSwCardD0Fee());

        //天天到账垫资费 busOpenType=20时必填
        bizContentMap.put("d1Fee", getD1Fee());

        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        //String sign= RSA256Util.sign(sb1.toString(),MERC_PRIVATE_FILE,MERC_PRIVATE_FILE_PASSWORD);
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 查询变更状态
     *
     * @throws Exception
     */
    public void queryCustChangeDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/queryCustChange";
        //测试 https://appdev.ysepay.com/openapi/smsc/queryCustChange
        //生产 https://ysgate.ysepay.com/openapi/smsc/queryCustChange

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.queryCustChange");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        /*byte[] byte1= RSA256Util.encrypt(YS_PUBLIC_CER_PATH, ByteUtil.hexStringToBytes(key));
        String check = Base64.encodeBase64String(byte1);*/
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //变更申请流水 变更申请成功后返回的
        bizContentMap.put("changeSysFlowId", "CHG202204200000139");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        //String sign= RSA256Util.sign(sb1.toString(),MERC_PRIVATE_FILE,MERC_PRIVATE_FILE_PASSWORD);
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 报备
     *
     * @throws Exception
     */
    public void sweepreportDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/saas/sweep/sweepreport";
        //测试 https://appdev.ysepay.com/openapi/smsc/saas/sweep/sweepreport
        //生产 https://ysgate.ysepay.com/openapi/smsc/saas/sweep/sweepreport

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.saas.sweep.sweepreport");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        /*byte[] byte1= RSA256Util.encrypt(YS_PUBLIC_CER_PATH, ByteUtil.hexStringToBytes(key));
        String check = Base64.encodeBase64String(byte1);*/
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //商户号
        bizContentMap.put("mercId", "826603057229704");
        //报备渠道
        bizContentMap.put("reportChannel", "NUCC_WECHAT");
        //mcc码
        bizContentMap.put("mccCd", "");
        //小程序APPID
        bizContentMap.put("appletAppid", "");
        //公众号
        bizContentMap.put("appid", "");
        //公众号授权目录
        bizContentMap.put("jsapiPath", "");
        //微信报备名称
        bizContentMap.put("wxReportNm", "");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        //String sign= RSA256Util.sign(sb1.toString(),MERC_PRIVATE_FILE,MERC_PRIVATE_FILE_PASSWORD);
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 重新报备
     *
     * @throws Exception
     */
    public void reportAgainDemo() throws Exception {
        //请求地址
        String HTTP_URL = HTTP_NET + "/openapi/smsc/saas/sweep/reportAgain";
        //测试 https://appdev.ysepay.com/openapi/smsc/saas/sweep/reportAgain
        //生产 https://ysgate.ysepay.com/openapi/smsc/saas/sweep/reportAgain

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.saas.sweep.reportAgain");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        /*byte[] byte1= RSA256Util.encrypt(YS_PUBLIC_CER_PATH, ByteUtil.hexStringToBytes(key));
        String check = Base64.encodeBase64String(byte1);*/
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //商户号
        bizContentMap.put("mercId", "826603057229704");
        //报备渠道
        bizContentMap.put("reportChannel", "NUCC_WECHAT");
        //mcc码
        bizContentMap.put("mccCd", "5799");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        //String sign= RSA256Util.sign(sb1.toString(),MERC_PRIVATE_FILE,MERC_PRIVATE_FILE_PASSWORD);
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    throw new Exception("验签失败");
                }
            } else {
                throw new Exception("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 商户入网
     */
    public void authorityOnline() throws Exception {
        //请求接口
        String HTTP_URL = HTTP_NET + "/openapi/smsc/saas/authority/online";
        //测试 https://appdev.ysepay.com/openapi/t1/smsc/addCustInfoApply
        //生产 https://ysgate.ysepay.com/openapi/t1/smsc/addCustInfoApply

        /** 1、封装请求参数，bizContent（业务参数，需要加密）和check（需要生成密钥并加密）后面设置值*/
        Map<String, String> reqMap = new HashMap<String, String>();
        //接口方法名，根据接口文档取值
        reqMap.put("method", "smsc.saas.authority.online");
        //请求时间
        reqMap.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        reqMap.put("charset", "utf-8");
        //请求流水号
        reqMap.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        reqMap.put("certId", CERT_ID);
        //版本号，默认1.0，按接口文档来
        reqMap.put("version", "1.0");

        /** 2、生成对业务参数加密的密钥*/
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 16; i++) {
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
        }
        String key = ByteUtil.toHexString(sb.toString());

        /** 3、使用银盛公钥对密钥key进行加密，得到加密的key并设置到请求参数check中。publicFilePath为存放银盛公钥的地址*/
        String check = GMSignUtils.encryptData(YS_PUBLIC_CER_PATH, key);
        //加密后的密钥
        reqMap.put("check", check);

        /** 4、封装业务参数,具体参数见文档，这里只是举例子*/
        Map<String, Object> bizContentMap = new HashMap<>();
        //商户号
        bizContentMap.put("mercId", "826267572100000");
        //开关选项  ON(开通);OFF(关闭)
        bizContentMap.put("option", "ON");
        JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(bizContentMap));

        /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
        byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
        String msgBizContent = Base64.encodeBase64String(bte);
        reqMap.put("bizContent", msgBizContent);

        /** 6、将请求参数进行sort排序，生成拼接的字符床，并使用接入方私钥对请求参数进行加签，并将加签的值存入请求参数sign中*/
        //6.1 排序生成拼接字符串
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for (String k : keys) {
            if ("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if (sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign = GMSignUtils.signMsgSM2(MERC_PRIVATE_FILE, MERC_PRIVATE_FILE_PASSWORD, sb1.toString());
        reqMap.put("sign", sign);

        /** 7、发送http请求获取返回结果，请求地址以文档为准*/
        try {
            String result = HttpRequestUtil.getDoPostResponse(HTTP_URL, reqMap, "UTF-8", null, 20 * 1000);
            byte[] res = Base64.decodeBase64(result);
            Map<String, String> resMap = (Map<String, String>) JSONObject.parse(new String(res, "UTF-8"));
            System.out.println("http请求返回的结果为:" + JSONObject.toJSONString(resMap));

            /** 8、对结果进行解密，并使用银盛公钥验签*/
            if (StringUtils.isNotBlank(resMap.get("sign"))) {
                byte[] srcData = GMSignUtils.getSignDataStr1(resMap).getBytes("UTF-8");
                GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(YS_PUBLIC_CER_PATH);
                boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(resMap.get("sign")), srcData);
                if (!validateSignResult) {
                    System.out.println("验签失败");
                    return;
                }
            } else {
                System.out.println("验签失败,未返回加签信息,可能是银盛未配置发起方或者发起方证书类型配置有误,返回结果提示为:{}" + resMap.get("msg"));
                return;
            }

            /** 9、针对自己的业务，根据返回的结果的code 和 subCode 做接入方的业务处理*/


            /** 10、使用上面生成的加密密钥key，解密返回的业务参数*/
            if (StringUtils.isNotBlank(resMap.get("businessData"))) {
                byte[] data_ = Base64.decodeBase64(resMap.get("businessData"));
                byte[] data = AESUtil.decrypt(data_, ByteUtil.hexStringToBytes(key));
                resMap.put("businessData", new String(data, "UTF-8"));
                System.out.println("解密后的业务参数:" + new String(data, "UTF-8"));
            }
            System.out.println("解密后的完整参数为:" + JSONObject.toJSONString(resMap));
        } catch (Exception e) {
            System.out.println("商户入网申请失败:" + e.getMessage());
        }
    }


    /**
     * 格式化当前日期时间字符串
     *
     * @return
     */
    private String getCurrentDateTime(String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(new Date());
    }

    /**
     * 获取基本信息
     *
     * @return
     */
    private Map<String, Object> getModeifyCustInfo() {
        Map<String, Object> custInfoMap = new HashMap<>();
        //代理商编号
        custInfoMap.put("agtMercId", "");
        //商户名称
        custInfoMap.put("mercName", "测试数据-修改");
        //商户简称
        custInfoMap.put("mercShortName", "测试数据-修改");
        //商户类型2 小微 3个体 4企业
        custInfoMap.put("mercType", "2");
        //mcc码 通过查询mcc码接口可以获取
        custInfoMap.put("mccCd", "5722");
        //联系人邮箱
        custInfoMap.put("contactMail", "10xxxxxxxx@qq.com");
        //联系人
        custInfoMap.put("contactMan", "张三");
        //联系人电话
        custInfoMap.put("contactPhone", "157xxxxxx53");
        //客户经理
        custInfoMap.put("cusMgrNm", "10xxxxxxxx@qq.com");
        //是否开通营销
        custInfoMap.put("isOpenMarket", "N");
        //异步通知地址
        custInfoMap.put("notifyUrl", "https://www.baidu.com");
        //备注
        custInfoMap.put("remark", "备注");
        return custInfoMap;
    }

    /**
     * 获取法人信息
     *
     * @return
     */
    private Map<String, Object> getModeifytCrpInfo() {
        Map<String, Object> crpInfoMap = new HashMap<>();
        //法人证件号
        crpInfoMap.put("crpCertNo", "42xxxxxxxxxxxxxx11");
        //法人证件类型
        crpInfoMap.put("crpCertType", "00");
        //证件开始日期
        crpInfoMap.put("certBgn", "20211007");
        //证件有效期
        crpInfoMap.put("certExpire", "29991231");
        //法人国籍
        crpInfoMap.put("crpNati", "249");
        //法人姓名
        crpInfoMap.put("crpNm", "张三");
        //法人手机号
        crpInfoMap.put("crpPhone", "157xxxxxx53");

        //法人地址
        crpInfoMap.put("crpAddr", "湖北省恩施市建始县");

        //实际控制人（默认同法人信息）,若传值，则姓名，证件类型，证件号，证件开始日期、结束日期必填
        Map<String, Object> actContrInfoMap = new HashMap<>();
        actContrInfoMap.put("name", "李九");
        actContrInfoMap.put("certType", "00");
        actContrInfoMap.put("certNo", "422822199302120514");
        actContrInfoMap.put("certBgn", "20210702");
        actContrInfoMap.put("certExpire", "20991230");
        actContrInfoMap.put("addr", "湖北省");
        crpInfoMap.put("actContrInfo", actContrInfoMap);

        //被授权人信息（法人结算同法人信息,非法人结算同开户人信息）,若传值，则姓名，证件类型，证件号，证件开始日期、结束日期必填
        Map<String, Object> authInfoMap = new HashMap<>();
        authInfoMap.put("name", "李九");
        authInfoMap.put("certType", "00");
        authInfoMap.put("certNo", "422822199302120514");
        authInfoMap.put("certBgn", "20210702");
        authInfoMap.put("certExpire", "20991230");
        authInfoMap.put("addr", "湖北省");
        crpInfoMap.put("authInfo", authInfoMap);

        //受益人(默认同法人)，最多三个受益人
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> bnfOneMap = new HashMap<>();
        bnfOneMap.put("name", "李九");
        bnfOneMap.put("certType", "00");
        bnfOneMap.put("certNo", "422822199302120514");
        bnfOneMap.put("certBgn", "20210702");
        bnfOneMap.put("certExpire", "20991230");
        bnfOneMap.put("addr", "湖北省武汉");
        list.add(bnfOneMap);

        Map<String, Object> bnfTwoMap = new HashMap<>();
        bnfTwoMap.put("name", "李四九");
        bnfTwoMap.put("certType", "00");
        bnfTwoMap.put("certNo", "422822199302120512");
        bnfTwoMap.put("certBgn", "20210702");
        bnfTwoMap.put("certExpire", "20991230");
        bnfTwoMap.put("addr", "湖北省武汉");
        list.add(bnfTwoMap);

        Map<String, Object> bnfThreeMap = new HashMap<>();
        bnfThreeMap.put("name", "李四九");
        bnfThreeMap.put("certType", "00");
        bnfThreeMap.put("certNo", "422822199302120513");
        bnfThreeMap.put("certBgn", "20210702");
        bnfThreeMap.put("certExpire", "20991230");
        bnfThreeMap.put("addr", "湖北省武汉");
        list.add(bnfThreeMap);
        crpInfoMap.put("bnfList", list);
        return crpInfoMap;
    }

    /**
     * 获取结算信息
     *
     * @return
     */
    private Map<String, Object> getModeifyStlAccInfo() {
        Map<String, Object> stlAccInfoMap = new HashMap<>();
        //是否平台内账户
        stlAccInfoMap.put("isSettInPlatAcc", "N");
        //是否非法人结算
        stlAccInfoMap.put("isUncrpSett", "N");
        //结算户名
        stlAccInfoMap.put("stlAccNm", "张三");
        //结算账号
        stlAccInfoMap.put("stlAccNo", "622909337260925515");
        //开户支行联行号
        stlAccInfoMap.put("bankSubCode", "309124000116");
        //结算账户类型
        stlAccInfoMap.put("stlAccType", "11");
        //银行预留手机号
        stlAccInfoMap.put("bankMobile", "157xxxxxx53");
        //开开户证件号
        stlAccInfoMap.put("openCertNo", "42xxxxxxxxxxxxxx11");
        return stlAccInfoMap;
    }

    /**
     * 获取营业信息
     *
     * @return
     */
    private Map<String, Object> getModeifyBusInfo() {
        Map<String, Object> busInfoMap = new HashMap<>();
        //营业执照号 非小微必填
        busInfoMap.put("busNo", "19");
        //营业执照名称 非小微必填
        busInfoMap.put("busNm", "机构测试商户1");
        //营业执照有效开始日期
        busInfoMap.put("busCertBgn", "");
        //营业执照有效期
        busInfoMap.put("busCertExpire", "29991221");
        //营业归属省代码
        busInfoMap.put("busProviceCode", "5800");
        //营业归属市代码
        busInfoMap.put("busCityCode", "5840");
        //营业归属区(县)代码
        busInfoMap.put("busAreaCode", "5843");
        //营业执照证件类型
        busInfoMap.put("busCertType", "19");
        //营业详细地址
        busInfoMap.put("busAddr", "故宫路一号");
        //注册地址
        busInfoMap.put("regAddr", "故宫路一号");
        return busInfoMap;
    }

    /**
     * 获取基本信息
     *
     * @return
     */
    private Map<String, Object> getCustInfo() {
        Map<String, Object> custInfoMap = new HashMap<>();
        //代理商编号
        custInfoMap.put("agtMercId", "");
        //商户名称
        custInfoMap.put("mercName", "测试数据");
        //商户简称
        custInfoMap.put("mercShortName", "");
        //商户类型2 小微 3个体 4企业
        custInfoMap.put("mercType", "2");
        //mcc码 通过查询mcc码接口可以获取
        custInfoMap.put("mccCd", "5722");
        //联系人邮箱
        custInfoMap.put("contactMail", "10xxxxxxxx@qq.com");
        //联系人
        custInfoMap.put("contactMan", "张三");
        //联系人电话
        custInfoMap.put("contactPhone", "187xxxxxx73");
        //客户经理
        custInfoMap.put("cusMgrNm", "10xxxxxxxx@qq.com");
        //是否开通营销
        custInfoMap.put("isOpenMarket", "N");
        //异步通知地址
        custInfoMap.put("notifyUrl", "https://www.baidu.com");
        //备注
        custInfoMap.put("remark", "备注");
        return custInfoMap;
    }

    /**
     * 获取法人信息
     *
     * @return
     */
    private Map<String, Object> getCrpInfo() {
        Map<String, Object> crpInfoMap = new HashMap<>();
        //法人证件号
        crpInfoMap.put("crpCertNo", "42xxxxxxxxxxxxxx11");
        //法人证件类型
        crpInfoMap.put("crpCertType", "00");
        //证件开始日期
        crpInfoMap.put("certBgn", "20211007");
        //证件有效期
        crpInfoMap.put("certExpire", "29991231");
        //法人国籍
        crpInfoMap.put("crpNati", "249");
        //法人姓名
        crpInfoMap.put("crpNm", "李xx");
        //法人手机号
        crpInfoMap.put("crpPhone", "187xxxxxx73");
        //法人地址
        crpInfoMap.put("crpAddr", "湖北省恩施市建始县");

        //实际控制人（默认同法人信息）,若传值，则姓名，证件类型，证件号，证件开始日期、结束日期必填
        Map<String, Object> actContrInfoMap = new HashMap<>();
        actContrInfoMap.put("name", "张三");
        actContrInfoMap.put("certType", "00");
        actContrInfoMap.put("certNo", "42xxxxxxxxxxxxxx11");
        actContrInfoMap.put("certBgn", "20210702");
        actContrInfoMap.put("certExpire", "20991230");
        actContrInfoMap.put("addr", "湖北省");
        crpInfoMap.put("actContrInfo", actContrInfoMap);

        //被授权人信息（法人结算同法人信息,非法人结算同开户人信息）,若传值，则姓名，证件类型，证件号，证件开始日期、结束日期必填
        Map<String, Object> authInfoMap = new HashMap<>();
        authInfoMap.put("name", "张三");
        authInfoMap.put("certType", "00");
        authInfoMap.put("certNo", "42xxxxxxxxxxxxxx11");
        authInfoMap.put("certBgn", "20210702");
        authInfoMap.put("certExpire", "20991230");
        authInfoMap.put("addr", "湖北省");
        crpInfoMap.put("authInfo", authInfoMap);

        //受益人(默认同法人)，最多三个受益人
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> bnfOneMap = new HashMap<>();
        bnfOneMap.put("name", "张三");
        bnfOneMap.put("certType", "00");
        bnfOneMap.put("certNo", "422822199302120514");
        bnfOneMap.put("certBgn", "20210702");
        bnfOneMap.put("certExpire", "20991230");
        bnfOneMap.put("addr", "湖北省");
        list.add(bnfOneMap);

        Map<String, Object> bnfTwoMap = new HashMap<>();
        bnfTwoMap.put("name", "李四");
        bnfTwoMap.put("certType", "00");
        bnfTwoMap.put("certNo", "422822199302120512");
        bnfTwoMap.put("certBgn", "20210702");
        bnfTwoMap.put("certExpire", "20991230");
        bnfTwoMap.put("addr", "湖北省");
        list.add(bnfTwoMap);

        Map<String, Object> bnfThreeMap = new HashMap<>();
        bnfThreeMap.put("name", "王五");
        bnfThreeMap.put("certType", "00");
        bnfThreeMap.put("certNo", "422822199302120513");
        bnfThreeMap.put("certBgn", "20210702");
        bnfThreeMap.put("certExpire", "20991230");
        bnfThreeMap.put("addr", "湖北省");
        list.add(bnfThreeMap);
        crpInfoMap.put("bnfList", list);
        return crpInfoMap;
    }

    /**
     * 获取结算信息
     *
     * @return
     */
    private Map<String, Object> getStlAccInfo() {
        Map<String, Object> stlAccInfoMap = new HashMap<>();
        //是否平台内账户
        stlAccInfoMap.put("isSettInPlatAcc", "N");
        //是否非法人结算
        stlAccInfoMap.put("isUncrpSett", "N");
        //结算户名
        stlAccInfoMap.put("stlAccNm", "李xx");
        //结算账号
        stlAccInfoMap.put("stlAccNo", "6217680302177758");
        //开户支行联行号
        stlAccInfoMap.put("bankSubCode", "105602070012");
        //结算账户类型
        stlAccInfoMap.put("stlAccType", "11");
        //银行预留手机号
        stlAccInfoMap.put("bankMobile", "187xxxxxx73");
        //开开户证件号
        stlAccInfoMap.put("openCertNo", "42xxxxxxxxxxxxxx11");
        return stlAccInfoMap;
    }

    /**
     * 获取营业信息
     *
     * @return
     */
    private Map<String, Object> getBusInfo() {
        Map<String, Object> busInfoMap = new HashMap<>();
        //营业执照号 非小微必填
        busInfoMap.put("busNo", "19");
        //营业执照名称 非小微必填
        busInfoMap.put("busNm", "机构测试商户1");
        //营业执照有效开始日期
        busInfoMap.put("busCertBgn", "");
        //营业执照有效期
        busInfoMap.put("busCertExpire", "29991221");
        //营业归属省代码
        busInfoMap.put("busProviceCode", "5800");
        //营业归属市代码
        busInfoMap.put("busCityCode", "5840");
        //营业归属区(县)代码
        busInfoMap.put("busAreaCode", "5843");
        //营业执照证件类型
        busInfoMap.put("busCertType", "19");
        //营业详细地址
        busInfoMap.put("busAddr", "故宫路一号");
        //注册地址
        busInfoMap.put("regAddr", "故宫路一号");
        return busInfoMap;
    }

    /**
     * 扫码工作日到账费率 busOpenType=00时必填
     *
     * @return
     */
    private Map<String, Object> getCodeScanT1Fee() {
        Map<String, Object> codeScanT1FeeMap = new HashMap<>();

        //微信扫码费率
        Map<String, Object> wxPayFeeMap = new HashMap<>();
        wxPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        wxPayFeeMap.put("rateFee", "0.60");//费率 单位为% 填0.53代表0.53%
        wxPayFeeMap.put("rateBottom", "60");//最低收费 单位为分

        //支付宝扫码费率
        Map<String, Object> aliPayFeeMap = new HashMap<>();
        aliPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        aliPayFeeMap.put("rateFee", "0.61");//费率 单位为% 填0.53代表0.53%
        aliPayFeeMap.put("rateBottom", "61");//最低收费 单位为分

        //银联一档借记卡扫码费率(>1000)
        Map<String, Object> bank1debitPayFeeMap = new HashMap<>();
        bank1debitPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        bank1debitPayFeeMap.put("rateFee", "0.62");//费率 单位为% 填0.53代表0.53%
        bank1debitPayFeeMap.put("rateBottom", "62");//最低收费 单位为分
        bank1debitPayFeeMap.put("rateTop", "1062");//最高收费 单位为分

        //银联一档贷记卡扫码费率(>1000)
        Map<String, Object> bank1creditPayFeeMap = new HashMap<>();
        bank1creditPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        bank1creditPayFeeMap.put("rateFee", "0.63");//费率 单位为% 填0.53代表0.53%
        bank1creditPayFeeMap.put("rateBottom", "63");//最低收费 单位为分

        //银联二档借记卡扫码费率(<=1000)
        Map<String, Object> bank2debitPayFeeMap = new HashMap<>();
        bank2debitPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        bank2debitPayFeeMap.put("rateFee", "0.64");//费率 单位为% 填0.53代表0.53%
        bank2debitPayFeeMap.put("rateBottom", "64");//最低收费 单位为分
        bank2debitPayFeeMap.put("rateTop", "1064"); //最高收费 单位为分

        //银联二档贷记卡扫码费率(<=1000)
        Map<String, Object> bank2creditPayFeeMap = new HashMap<>();
        bank2creditPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        bank2creditPayFeeMap.put("rateFee", "0.65");//费率 单位为% 填0.53代表0.53%
        bank2creditPayFeeMap.put("rateBottom", "65");//最低收费 单位为分

        codeScanT1FeeMap.put("wxPayFee", wxPayFeeMap);
        codeScanT1FeeMap.put("aliPayFee", aliPayFeeMap);
        codeScanT1FeeMap.put("bank1debitPayFee", bank1debitPayFeeMap);
        codeScanT1FeeMap.put("bank1creditPayFee", bank1creditPayFeeMap);
        codeScanT1FeeMap.put("bank2debitPayFee", bank2debitPayFeeMap);
        codeScanT1FeeMap.put("bank2creditPayFee", bank2creditPayFeeMap);
        return codeScanT1FeeMap;
    }

    /**
     * 扫码实时到账垫资费 busOpenType=01时必填
     *
     * @return
     */
    private Map<String, Object> getCodeScanD0Fee() {
        Map<String, Object> codeScanT1FeeMap = new HashMap<>();
        //扫码实时到账垫资费
        codeScanT1FeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        codeScanT1FeeMap.put("rateFee", "0.66");//费率 单位为% 填0.53代表0.53%
        codeScanT1FeeMap.put("rateBottom", "66");//最低收费 单位为分
        return codeScanT1FeeMap;
    }

    /**
     * 刷卡工作日到账费率 busOpenType=10时必填
     *
     * @return
     */
    private Map<String, Object> getSwCardT1Fee() {
        Map<String, Object> resultMap = new HashMap<>();

        //借记卡费率
        Map<String, Object> debitPayFeeMap = new HashMap<>();
        debitPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        debitPayFeeMap.put("rateFee", "0.67");//费率 单位为% 填0.53代表0.53%
        debitPayFeeMap.put("rateBottom", "67");//最低收费 单位为分
        debitPayFeeMap.put("rateTop", "1067");//最高收费 单位为分

        //贷记卡费率
        Map<String, Object> creditPayFeeMap = new HashMap<>();
        creditPayFeeMap.put("rateType", "0");//收费方式 这里只支持0按百分比
        creditPayFeeMap.put("rateFee", "0.68");//费率 单位为% 填0.53代表0.53%
        creditPayFeeMap.put("rateBottom", "68");//最低收费 单位为分

        resultMap.put("debitPayFee", debitPayFeeMap);
        resultMap.put("creditPayFee", creditPayFeeMap);
        return resultMap;
    }

    /**
     * 刷卡实时到账垫资费 busOpenType=11时必填
     *
     * @return
     */
    private Map<String, Object> getSwCardD0Fee() {
        Map<String, Object> resultMap = new HashMap<>();

        //借记卡费率
        Map<String, Object> debitPayFeeMap = new HashMap<>();
        debitPayFeeMap.put("rateType", "0");//收费方式 0 按百分比 1按固定金额
        debitPayFeeMap.put("rateFee", "0.69");//费率 按百分比时单位为% 按固定金额时 单位为分
        debitPayFeeMap.put("rateBottom", "69");//最低收费 单位为分 按百分比时生效
        debitPayFeeMap.put("rateTop", "1069");//最高收费 单位为分 按百分比时生效

        //贷记卡费率
        Map<String, Object> creditPayFeeMap = new HashMap<>();
        creditPayFeeMap.put("rateType", "0");//收费方式 0 按百分比 1按固定金额
        creditPayFeeMap.put("rateFee", "0.70");//费率 按百分比时单位为% 按固定金额时 单位为分
        creditPayFeeMap.put("rateBottom", "70");//最低收费 单位为分 按百分比时生效
        creditPayFeeMap.put("rateTop", "1070");//最高收费 单位为分 按百分比时生效

        resultMap.put("debitPayFee", debitPayFeeMap);
        resultMap.put("creditPayFee", creditPayFeeMap);
        return resultMap;
    }

    /**
     * 天天到账垫资费 busOpenType=20时必填
     *
     * @return
     */
    private Map<String, Object> getD1Fee() {
        Map<String, Object> d1FeeMap = new HashMap<>();
        d1FeeMap.put("rateType", "0");//收费方式 0 按百分比 1按固定金额
        d1FeeMap.put("rateFee", "0.71");//费率 按百分比时单位为% 按固定金额时 单位为分
        d1FeeMap.put("rateBottom", "71");//最低收费 单位为分 按百分比时生效
        return d1FeeMap;
    }

}
